package com.devframe.srtp.server.support;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpHeaders;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;
import org.jboss.netty.handler.codec.http.multipart.Attribute;
import org.jboss.netty.handler.codec.http.multipart.DefaultHttpDataFactory;
import org.jboss.netty.handler.codec.http.multipart.DiskAttribute;
import org.jboss.netty.handler.codec.http.multipart.DiskFileUpload;
import org.jboss.netty.handler.codec.http.multipart.FileUpload;
import org.jboss.netty.handler.codec.http.multipart.HttpDataFactory;
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData;
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException;
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder.IncompatibleDataDecoderException;
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException;
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;
import org.jboss.netty.util.CharsetUtil;

import com.devframe.srtp.SRTPConstants;
import com.devframe.srtp.server.SRTPServerContainer;
import com.devframe.srtp.server.file.SRTPFileHandlerFactory;
import com.devframe.srtp.server.parse.SRTPParam;
import com.devframe.srtp.server.parse.SRTPParamParser;
import com.devframe.srtp.util.enumobj.EnumSRTPAction;

public class SRTPServerHandler extends SimpleChannelUpstreamHandler {
	private HttpRequest request;

	private boolean readingChunks;
	
	private final StringBuilder responseContent = new StringBuilder();

	private static final HttpDataFactory factory = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE);
	
	private HttpPostRequestDecoder decoder;
	
	private SRTPParam requestParams=new SRTPParam();
	static {
		DiskFileUpload.deleteOnExitTemporaryFile = false; // should delete
		DiskFileUpload.baseDirectory =SRTPServerContainer.getInstance().getSRTPBaseDirectory(); // system temp directory
		DiskAttribute.deleteOnExitTemporaryFile = false; // should delete
		DiskAttribute.baseDirectory = SRTPServerContainer.getInstance().getSRTPBaseDirectory(); // system temp directory
	}

	public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		if (decoder != null) {
			decoder.cleanFiles();
		}
	}
	  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
		   if (!readingChunks) {
			   if (decoder != null) {
	                decoder.cleanFiles();
	                decoder = null;
	            }
	            HttpRequest request = this.request = (HttpRequest) e.getMessage();
	            URI uri = new URI(request.getUri());
	            //必须包含有form的请求
	            if (!uri.getPath().startsWith("/form")) {
	                // Write Menu
	                writeMenu(e);
	                return;
	            }
	            try {
	                decoder = new HttpPostRequestDecoder(factory, request);
	            } catch (ErrorDataDecoderException e1) {
	            	e1.printStackTrace();
	                e1.printStackTrace();
	                responseContent.append(e1.getMessage());
	                writeResponse(e.getChannel());
	                Channels.close(e.getChannel());
	                return;
	            } catch (IncompatibleDataDecoderException e1) {
	            	e1.printStackTrace();
	                responseContent.append(e1.getMessage());
	                responseContent.append("\r\n\r\nEND OF GET CONTENT\r\n");
	                writeResponse(e.getChannel());
	                return;
	            }

	        if (request.isChunked()) {
	            readingChunks = true;
	        } else {
	            // Not chunk version
	        	//解析参数
	        	SRTPParamParser.parseParams(decoder, requestParams);
//	            responseContent.append(requestParams.toString());
	            String result=SRTPFileHandlerFactory.process(requestParams);
	        	responseContent.append(result);
	            writeResponse(e.getChannel());
                //写入完成
                e.getFuture().addListener(ChannelFutureListener.CLOSE);
	        }
		   } else {
	            // New chunk is received
	            HttpChunk chunk = (HttpChunk) e.getMessage();
	            try {
	                decoder.offer(chunk);
	            } catch (ErrorDataDecoderException e1) {
	                e1.printStackTrace();
	                responseContent.append(e1.getMessage());
	                writeResponse(e.getChannel());
	                Channels.close(e.getChannel());
	                return;
	            }
//	            responseContent.append('o');
	            if (chunk.isLast()) {
	                //修改文件名称
	                readingChunks = false;
		        	//解析参数
		        	SRTPParamParser.parseParams(decoder, requestParams);
		        	//进行操作
		        	String result=SRTPFileHandlerFactory.process(requestParams);
		        	responseContent.append(result);
		        	
	                writeResponse(e.getChannel());
	                //写入完成
	                e.getFuture().addListener(ChannelFutureListener.CLOSE);
	            }
	        }
	  }
	  private void writeResponse(Channel channel) {
	        // Convert the response content to a ChannelBuffer.
	        ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
	        responseContent.setLength(0);
	        // Decide whether to close the connection or not.
	        boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request.getHeader(HttpHeaders.Names.CONNECTION)) ||
	                request.getProtocolVersion().equals(HttpVersion.HTTP_1_0) &&
	                !HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.getHeader(HttpHeaders.Names.CONNECTION));
	        
	        HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK);
	        response.setContent(buf);
	        response.setHeader(HttpHeaders.Names.CONTENT_TYPE,"text/plain; charset=UTF-8");
	        if (!close) {
	            response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes()));
	        }
	        ChannelFuture future = channel.write(response);
	        if (close) {
	            future.addListener(ChannelFutureListener.CLOSE);
	        }
	    }
	  
	  
	  private void writeMenu(MessageEvent e) {
	        // print several HTML forms
	        // Convert the response content to a ChannelBuffer.
	        responseContent.setLength(0);

	        // create Pseudo Menu
	        responseContent.append("<html>");
	        responseContent.append("<head>");
	        responseContent.append("<title>Netty Test Form</title>\r\n");
	        responseContent.append("</head>\r\n");
	        responseContent.append("<body bgcolor=white><style>td{font-size: 12pt;}</style>");
	        responseContent.append("<table border=\"0\">");
	        responseContent.append("<tr>");
	        responseContent.append("<td>");
	        responseContent.append("<h1>Netty Test Form</h1>");
	        responseContent.append("Choose one FORM");
	        responseContent.append("</td>");
	        responseContent.append("</tr>");
	        responseContent.append("</table>\r\n");

	        // GET
	        responseContent
	                .append("<CENTER>GET FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
	        responseContent.append("<FORM ACTION=\"/formget\" METHOD=\"POST\">");
	        responseContent
	                .append("<input type=hidden name=getform value=\"POST\">");
	        responseContent.append("<table border=\"0\">");
	        responseContent
	                .append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>");
	        responseContent
	                .append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>");
	        responseContent
	                .append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
	        responseContent.append("</td></tr>");
	        responseContent
	                .append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
	        responseContent
	                .append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
	        responseContent.append("</table></FORM>\r\n");
	        responseContent.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");

	        // POST
	        responseContent.append("<CENTER>POST FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
	        responseContent.append("<FORM ACTION=\"/formpost\" METHOD=\"POST\">");
	        responseContent.append("<input type=hidden name=getform value=\"POST\">");
	        responseContent.append("<table border=\"0\">");
	        responseContent.append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>");
	        responseContent.append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>");
	        responseContent
	                .append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
	        responseContent
	                .append("<tr><td>Fill with file (only file name will be transmitted): <br> " +
	                        "<input type=file name=\"myfile\">");
	        responseContent.append("</td></tr>");
	        responseContent.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
	        responseContent
	                .append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
	        responseContent.append("</table></FORM>\r\n");
	        responseContent
	                .append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");

	        // POST with enctype="multipart/form-data"
	        responseContent.append("<CENTER>POST MULTIPART FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
	        responseContent.append("<FORM ACTION=\"/formpostmultipart\" ENCTYPE=\"multipart/form-data\" METHOD=\"POST\">");
	        responseContent.append("<input type=hidden name=getform value=\"POST\">");
	        
	        responseContent.append("<input type=hidden name=action value=\""+EnumSRTPAction.UPLOAD_FILE.getValue()+"\">");
	        responseContent.append("<table border=\"0\">");
	        responseContent.append("<tr><td>账户: <br> <input type=text name=\""+SRTPConstants.USER_NAME_KEY+"\" value=\""+SRTPConstants.DEFAULT_ACCOUNT.getUserName()+"\" size=10></td></tr>");
	        responseContent.append("<tr><td>产生缩略图: <br> <select type=file name=\""+SRTPConstants.THUMB_MARK_KEY+"\">");
	        responseContent.append("<option value=\""+SRTPConstants.THUMB_MARK_YES+"\">是</option>");
	        responseContent.append("<option value=\""+SRTPConstants.THUMB_MARK_NO+"\">否</option>");
	        responseContent.append("</select></td></tr>");
	        responseContent.append("<tr><td>Fill with file: <br> <input type=file name=\"myfile\">");
	        responseContent.append("</td></tr>");
	        responseContent.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
	        responseContent
	                .append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
	        responseContent.append("</table></FORM>\r\n");
	        responseContent
	                .append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");

	        responseContent.append("</body>");
	        responseContent.append("</html>");

	        ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
	        // Build the response object.
	        HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK);
	        response.setContent(buf);
	        response.setHeader(HttpHeaders.Names.CONTENT_TYPE,"text/html; charset=UTF-8");
	        response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes()));
	        // Write the response.
	        e.getChannel().write(response);
	    }

}
